package com.allinpay.merchantweb.common.utils;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.dom.DOMValidateContext;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.encoders.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
 * 数据加密工具类
 * 
 * @author yuyj
 * @date 20180130
 *
 */
public class SecurityUtils {

	private static final Logger logger = LoggerFactory.getLogger(SecurityUtils.class);
	
	
	/**
	 * 执行初始化操作，将 BouncyCastleProvider添加到java.security.Security中
	 */

	/*
	 * static { Secu rity.addProvider(new BouncyCastleProvider()); }
	 */

	static {
		try {
			Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
		}catch(Exception e) {
			e.printStackTrace();
		}
		
	}
	
	private SecurityUtils() {
	}

	/**
	 * 对数据做MD5摘要
	 * 
	 * @param aData
	 * @return
	 * @throws SecurityException
	 */
	public static String MD5Encode(String aData) throws Exception {
		String resultString = null;

		MessageDigest md = MessageDigest.getInstance("MD5");
		resultString = bytes2HexString(md.digest(aData.getBytes("UTF-8")));

		return resultString;
	}

	public static String bytes2HexString(byte[] b) {
		String ret = "";
		for (int i = 0; i < b.length; i++) {
			String hex = Integer.toHexString(b[i] & 0xFF);
			if (hex.length() == 1) {
				hex = '0' + hex;
			}
			ret += hex.toUpperCase();
		}
		return ret;
	}

	/**
	 * 获得公钥
	 * 
	 * @param modulus
	 * @param publicExponent
	 * @return
	 * @throws Exception
	 */
	public static PublicKey getPublicKey(String modulus, String publicExponent)
			throws Exception {

		BigInteger m = new BigInteger(modulus, 16);
		BigInteger e = new BigInteger(publicExponent, 16);

		RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
		KeyFactory keyFactory = KeyFactory.getInstance("RSA",
				new BouncyCastleProvider());
		PublicKey publicKey = keyFactory.generatePublic(keySpec);

		return publicKey;
	}

	/**
	 * 从modulus和exponent生成rsa的私钥，要求两个参数都是16进制格式
	 * 
	 * @param modulus
	 *            16进制
	 * @param privateExponent
	 *            16进制
	 * @return
	 * @throws Exception
	 * 
	 */
	public static PrivateKey getPrivateKey(String modulus,
			String privateExponent) throws Exception {

		BigInteger m = new BigInteger(modulus, 16);
		BigInteger e = new BigInteger(privateExponent, 16);

		RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);

		KeyFactory keyFactory = KeyFactory.getInstance("RSA",
				new BouncyCastleProvider());

		PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

		return privateKey;
	}

	/**
	 * 根据alias别名从store文件获得私钥信息
	 * 
	 * @param storePath
	 *            store文件地址
	 * @param alias
	 *            别名
	 * @param storePass
	 *            store访问明码
	 * @param storeType
	 *            store类型 为空时为默认值
	 * @return 私钥
	 * @throws Exception
	 */
	@Deprecated
	public static PrivateKey getPrivateKeyFromStore(String storePath,
			String alias, String storePass, String storeType) throws Exception {

		// KeyTool中生成KeyStore时设置的alias
		// alias = "paymentSign";
		// KeyTool中生成KeyStore时设置的storetype
		// storeType = "JCEKS";
		// KeyTool中生成KeyStore时设置的storepass
		char[] pw = storePass.toCharArray();
		// KeyTool中已生成的KeyStore文件
		// storePath = "C:/app/payment.keystore";
		storeType = "JCEKS";
		storeType = null == storeType ? KeyStore.getDefaultType() : storeType;

		KeyStore keyStore = KeyStore.getInstance(storeType);

		InputStream is = new FileInputStream(storePath);

		keyStore.load(is, pw);

		// 返回私钥
		return (PrivateKey) keyStore.getKey(alias, pw);
	}
	
	/**
	 * 从keyStore中获取私钥
	 * @param storePath
	 * @param alias
	 * @param storePass
	 * @param storeType
	 * @return
	 * @throws Exception
	 */
	public static PrivateKey getPriKeyFromStore(String storePath,
			String alias, String storePass, String storeType) throws Exception {
	
		char[] pw = storePass.toCharArray();
		
		if(StringUtil.isEmpty(storeType))
		{
			storeType = KeyStore.getDefaultType();
		}

		//获得KeyStore对象
		KeyStore keyStore = KeyStore.getInstance(storeType,new BouncyCastleProvider());

		//加载KeyStore库
		InputStream is = new FileInputStream(storePath);

		keyStore.load(is, pw);
	
		// 返回私钥
		return (PrivateKey) keyStore.getKey(alias, pw);
	}
	
	/**
	 * 从keyStore中获取私钥
	 * @param storePath
	 * @param alias
	 * @param storePass
	 * @param storeType
	 * @return
	 * @throws Exception
	 */
	public static PublicKey getPubKeyFromStore(String storePath,
			String alias, String storePass, String storeType) throws Exception {
	
		char[] pw = storePass.toCharArray();
		
		if(StringUtil.isEmpty(storeType))
		{
			storeType = KeyStore.getDefaultType();
		}

		//获得KeyStore对象
		KeyStore keyStore = KeyStore.getInstance(storeType);

		//加载KeyStore库
		InputStream is = new FileInputStream(storePath);

		keyStore.load(is, pw);
	
		// 返回公钥
		return keyStore.getCertificate(alias).getPublicKey();
	}

	/**
	 * 从keyStore中获取证书Id
	 * @param storePath
	 * @param alias
	 * @param storePass
	 * @param storeType
	 * @return
	 * @throws Exception
	 */
	public static String getCertIdFromStore(String storePath,
			String alias, String storePass, String storeType) throws Exception {
	
		char[] pw = storePass.toCharArray();
		
		if(null == storeType)
		{
			storeType = KeyStore.getDefaultType();
		}

		//获得KeyStore对象
		KeyStore keyStore = KeyStore.getInstance(storeType,new BouncyCastleProvider());

		//加载KeyStore库
		InputStream is = new FileInputStream(storePath);

		keyStore.load(is, pw);
	
		// 返回证书
		X509Certificate cert = (X509Certificate) keyStore
				.getCertificate(alias);
		
		return cert.getSerialNumber().toString();
	}
	
	/**
	 * 从keyStore中获取证书Encode
	 * @param storePath
	 * @param alias
	 * @param storePass
	 * @param storeType
	 * @return
	 * @throws Exception
	 */
	public static byte[] getEncodeFromStore(String storePath,
			String alias, String storePass, String storeType) throws Exception {
	
		char[] pw = storePass.toCharArray();
		
		if(null == storeType)
		{
			storeType = KeyStore.getDefaultType();
		}

		//获得KeyStore对象
		KeyStore keyStore = KeyStore.getInstance(storeType,new BouncyCastleProvider());

		//加载KeyStore库
		InputStream is = new FileInputStream(storePath);

		keyStore.load(is, pw);
	
		// 返回证书
		X509Certificate cert = (X509Certificate) keyStore
				.getCertificate(alias);
		
		return cert.getEncoded();
	}
	
	/**
	 * 用私钥对数据签名,签名算法: SHA1withRSA
	 * 
	 * @param src
	 *            明文数据
	 * @param privateKey
	 *            私钥对象 可直接使用
	 * @return 加密后密文
	 * @throws SecurityException
	 */
	public static String signByRSAwithSHA1(String src, PrivateKey priKey)
			throws NoSuchAlgorithmException, InvalidKeyException,
			SignatureException, SecurityException {
		Security.addProvider(new BouncyCastleProvider());
		Signature sigEng = Signature.getInstance("SHA1withRSA");

		sigEng.initSign(priKey);
		sigEng.update(src.getBytes());

		byte[] signature = sigEng.sign();
		String signMsg = CodeUtil.bytes2HexString(signature);

		return signMsg;
	}

	/**
	 * 公钥验证
	 * 
	 * @param pubKey
	 * @param srcBytes
	 * @param signBytes
	 * @param signAlg
	 * @return
	 */
	public static boolean verifyByPubKey(Key pubKey, byte[] srcBytes,
			byte[] signBytes, String signAlg) {
		boolean result = false;
		try {
			Signature sign = Signature.getInstance(signAlg,
					new BouncyCastleProvider());

			sign.initVerify((PublicKey) pubKey);
			sign.update(srcBytes);
			result = sign.verify(signBytes);
		} catch (NoSuchAlgorithmException e) {
			// LoggerUtil.error("公钥验签 - 无效算法：");
		} catch (InvalidKeyException e) {
			// LoggerUtil.error("公钥验签 - 无效的密钥：");
		} catch (SignatureException e) {
			// LoggerUtil.error("公钥验签 - 签名异常：");
		}

		return result;
	}

	/**
	 * 加签
	 * 
	 * @param priKey
	 * @param srcBytes
	 * @param signAlg
	 * @return
	 */
	public static byte[] signByPriKey(Key priKey, byte[] srcBytes,
			String signAlg) {
		// 签名
		byte[] signBytes = null;
		try {
			Signature sign = Signature.getInstance(signAlg,
					new BouncyCastleProvider());
			sign.initSign((PrivateKey) priKey);
			sign.update(srcBytes);
			signBytes = sign.sign();
		} catch (NoSuchAlgorithmException e) {
			// LoggerUtil.error("私钥签名 - 无效算法：");
		} catch (InvalidKeyException e) {
			// LoggerUtil.error("私钥签名 - 无效的密钥：");
		} catch (SignatureException e) {
			// LoggerUtil.error("私钥签名 - 签名异常：");
		}

		return signBytes;
	}
	
	/**
	 * 加签(Xml)
	 * Xml内部生成Signature标签
	 * 
	 * @param priKey
	 * @param srcBytes
	 * @param signAlg
	 * @return
	 * @throws Exception 
	 */
	public static byte[] signXmlByPriKey(Key priKey, byte[] srcBytes) throws Exception {
		
		// 签名
		byte[] signBytes = null;
				
		try {
			
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			dbf.setNamespaceAware(true);
			Document doc = dbf.newDocumentBuilder().parse(
					new ByteArrayInputStream(srcBytes));
	
			XMLSignatureFactory factory = XMLSignatureFactory
					.getInstance("DOM");
			Transform envelopedTransform = factory.newTransform(
					Transform.ENVELOPED, (TransformParameterSpec) null);
			DigestMethod digestMethod = factory.newDigestMethod(
					DigestMethod.SHA1, null);
			CanonicalizationMethod canonicalizationMethod = factory
					.newCanonicalizationMethod(
							CanonicalizationMethod.INCLUSIVE,
							(C14NMethodParameterSpec) null);
			SignatureMethod signatureMethod = factory.newSignatureMethod(
					SignatureMethod.RSA_SHA1, null);
			Reference ref = factory.newReference("", digestMethod, Collections
					.singletonList(envelopedTransform), null, null);
			SignedInfo si = factory.newSignedInfo(canonicalizationMethod,
					signatureMethod, Collections.singletonList(ref));
			XMLSignature signature = factory.newXMLSignature(si, null);
			DOMSignContext domSignContext = new DOMSignContext(priKey, doc
					.getDocumentElement());
			signature.sign(domSignContext);
			TransformerFactory transformerFactory = TransformerFactory
					.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			transformer
					.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
			ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
			StreamResult streamResult = new StreamResult(outputStream);
			transformer.transform(new DOMSource(doc), streamResult);
			signBytes =  outputStream.toByteArray();
		}
		catch (Exception e) {
		   throw e;
		}
		
		return signBytes;
	}
	
	/**
	 * 使用公钥，对传入的XML进行校验，如果校验成功，返回true，否则，返回false。
	 * 在校验的过程中，会将XML原文加载为DOM对象，在DOM中优先寻找签名元素，如果没有找到或者数量不止1个，则直接返回false。
	 * 
	 * @param inputBytes
	 *            XML报文的bytes
	 * @param pubKey
	 *            公钥对象
	 * @return 校验结果，成功：true，失败：false
	 * @throws Exception
	 */
	public static boolean verifyXmlByPubKey(byte[] inputBytes, PublicKey pubKey)
			throws Exception {
		
		try {
			
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			dbf.setNamespaceAware(true);
			InputStream inputStream = new ByteArrayInputStream(inputBytes);
			Document document = dbf.newDocumentBuilder().parse(inputStream);
			
			/*
			 * 从XML原文中，找到签名报文元素。
			 * 如果找不到该节点，或者该节点的数量不为1，直接返回false。
			 */
			Node signatureNode = null;
			NodeList childNodes = document.getElementsByTagNameNS(XMLSignature.XMLNS,"Signature");
			if (childNodes.getLength() == 1) {
				signatureNode = childNodes.item(0);
			} else if (childNodes.getLength() == 0) {
				
				return false;
			} else {
			
				return false;
			}
			DOMValidateContext valContext = new DOMValidateContext(pubKey,
					signatureNode);
			XMLSignatureFactory factory = XMLSignatureFactory
					.getInstance("DOM");
			XMLSignature signature = factory.unmarshalXMLSignature(valContext);
			if (!signature.validate(valContext)) {
			
				return false;
			} else {
				return true;
			}
		} catch (Exception e) {
		
			throw e;
		}
	}

	/**
	 * 私钥解密过程
	 * 
	 * @param privateKey
	 *            私钥
	 * @param cipherData
	 *            密文数据
	 * @return 明文
	 * @throws Exception
	 *             解密过程中的异常信息
	 */
	public static byte[] decryptByPriKey(PrivateKey privateKey,
			byte[] cipherData) throws Exception {
		byte[] output = null;
		if (privateKey == null) {
			throw new Exception("解密私钥为空, 请设置");
		}
		Cipher cipher = null;
		try {
			// 使用默认RSA
			cipher = Cipher.getInstance("RSA");
			// cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
			cipher.init(Cipher.DECRYPT_MODE, privateKey);
			output = cipher.doFinal(cipherData);

		} catch (NoSuchAlgorithmException e) {
			// throw new Exception("无此解密算法");
		} catch (NoSuchPaddingException e) {
			// e.printStackTrace();
			// return null;
		} catch (InvalidKeyException e) {
			// throw new Exception("解密私钥非法,请检查");
		} catch (IllegalBlockSizeException e) {
			// throw new Exception("密文长度非法");
		} catch (BadPaddingException e) {
			// throw new Exception("密文数据已损坏");
		}

		return output;
	}
	
	/**
	 * 私钥解密过程
	 * 
	 * @param privateKey
	 *            私钥
	 * @param cipherData
	 *            密文数据
	 * @return 明文
	 * @throws Exception
	 *             解密过程中的异常信息
	 */
	public static byte[] encryptByPubKey(PublicKey publicKey,
			byte[] cipherData) throws Exception {
		byte[] output = null;
		if (publicKey == null) {
			throw new Exception("加密公钥为空, 请设置");
		}
		Cipher cipher = null;
		try {
			// 使用默认RSA
			cipher = Cipher.getInstance("RSA");
			// cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
			cipher.init(Cipher.ENCRYPT_MODE, publicKey);
			output = cipher.doFinal(cipherData);

		} catch (NoSuchAlgorithmException e) {
			// throw new Exception("无此解密算法");
		} catch (NoSuchPaddingException e) {
			// e.printStackTrace();
			// return null;
		} catch (InvalidKeyException e) {
			// throw new Exception("解密私钥非法,请检查");
		} catch (IllegalBlockSizeException e) {
			 throw new Exception("密文长度非法");
		} catch (BadPaddingException e) {
			// throw new Exception("密文数据已损坏");
		}

		return output;
	}

	/** 
     * 从文件中输入流中加载公钥 
     * @param in 公钥输入流 
     * @throws Exception 加载公钥时产生的异常 
     */  
    public static PublicKey loadPublicKey(InputStream in) throws Exception{  
        try {  
            BufferedReader br= new BufferedReader(new InputStreamReader(in));  
            String readLine= null;  
            StringBuilder sb= new StringBuilder();  
            while((readLine= br.readLine())!=null){  
                if(readLine.charAt(0)=='-'){  
                    continue;  
                }else{  
                    sb.append(readLine);  
                    sb.append('\r');  
                }  
            }  
            return loadPublicKey(sb.toString());  
        } catch (IOException e) {  
            throw new Exception("公钥数据流读取错误");  
        } catch (NullPointerException e) {  
            throw new Exception("公钥输入流为空");  
        } catch (Exception e) {  
            throw e;  
        }  
    }  
	
    /** 
     * 从文件中加载私钥 
     * @param in 私钥输入流  
     * @param pkcs PKCS标准
     * @return 是否成功 
     * @throws Exception  
     */  
    public static PrivateKey loadPrivateKey(InputStream in,String pkcs) throws Exception{  
        try {  
            BufferedReader br= new BufferedReader(new InputStreamReader(in));  
            String readLine= null;  
            StringBuilder sb= new StringBuilder();  
            while((readLine= br.readLine())!=null){  
                if(readLine.charAt(0)=='-'){  
                    continue;  
                }else{  
                    sb.append(readLine);  
                    sb.append('\r');  
                }  
            }  
            if("PKCS1".equals(pkcs)){
            	return loadPrivateKeyWithPcks1(sb.toString()); 
            }else if("PKCS8".equals(pkcs)){
            	return loadPrivateKeyWithPcks8(sb.toString());  
            }else{
            	return loadPrivateKeyWithPcks1(sb.toString());  //默认
            }
        } catch (IOException e) {  
            throw new Exception("私钥数据读取错误");  
        } catch (NullPointerException e) {  
            throw new Exception("私钥输入流为空");  
        } catch (Exception e) {  
            throw e;  
        }  
    }  
	
	/**
	 *  载入私钥 PKCS8
	 * @param privateKeyStr
	 * @return
	 * @throws Exception
	 */
	public static  PrivateKey loadPrivateKeyWithPcks8(String privateKeyStr) throws Exception{
		try {  
            byte[] buffer= Base64.decode(privateKeyStr);
            
            PKCS8EncodedKeySpec keySpec= new PKCS8EncodedKeySpec(buffer);  
            KeyFactory keyFactory= KeyFactory.getInstance("RSA");  
            return  (RSAPrivateKey) keyFactory.generatePrivate(keySpec);  
        } catch (NoSuchAlgorithmException e) {  
            throw new Exception("无此算法");  
        } catch (NullPointerException e) {  
            throw new Exception("私钥数据为空");  
        } catch (Exception e) {  
            throw e;  
        }  
	}
	
	
	/**
	 *  载入私钥 PKCS1
	 * @param privateKeyStr
	 * @return
	 * @throws Exception
	 */
	public static RSAPrivateKey loadPrivateKeyWithPcks1(String privateKeyStr) throws Exception{
        try {
        	 byte[] buffer= Base64.decode(privateKeyStr);
            RSAPrivateKeyStructure asn1PrivKey = new RSAPrivateKeyStructure((ASN1Sequence)ASN1Sequence.fromByteArray(buffer));
            RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(asn1PrivKey.getModulus(), asn1PrivKey.getPrivateExponent());
            KeyFactory keyFactory= KeyFactory.getInstance("RSA"); 
            return (RSAPrivateKey)keyFactory.generatePrivate(keySpec);
        } catch (Exception e) {
        	throw e;  
        }
    }

	
	/**
	 *  载入公钥
	 * @param publicKeyKeyStr
	 * @return
	 * @throws Exception
	 */
	public static  PublicKey loadPublicKey(String publicKeyKeyStr) throws Exception{
		try {  
            byte[] buffer= Base64.decode(publicKeyKeyStr);
            KeyFactory keyFactory= KeyFactory.getInstance("RSA"); 
            X509EncodedKeySpec keySpec= new X509EncodedKeySpec(buffer);  
            return (RSAPublicKey) keyFactory.generatePublic(keySpec);  
        } catch (NoSuchAlgorithmException e) {  
            throw new Exception("无此算法");  
        } catch (NullPointerException e) {  
            throw new Exception("公钥数据为空");  
        } catch (Exception e) {  
            throw e;  
        }  
		
	}
	
	/**
	 * 把key=value追加到加密/签名字符串最后.
	 * 
	 * @param buf
	 * @param key
	 * @param value
	 */
	public static void appendSignPara(StringBuffer buf, String key, String value) {
		if (!StringUtil.isEmpty(value)) {
			buf.append(key).append('=').append(value).append('&');
		}
	}
	
	/**
	 * 把key=value追加到加密/签名字符串的末尾.字符串不再继续增加新的key=value.
	 * 
	 * @param buf
	 * @param key
	 * @param value
	 */
	public static void appendLastSignPara(StringBuffer buf, String key,
			String value) {
		if (!StringUtil.isEmpty(value)) {
			buf.append(key).append('=').append(value);
		}
	}
	
	/**
	 * key=value排序
	 * 
	 * @param map
	 */
	public static String orderMap2Str(Map<String, Object> map) {
        Set<String> keySet = new TreeSet(map.keySet());
        StringBuilder sb = new StringBuilder();
        for (String key : keySet) {
            if (Map.class.isInstance(map.get(key))
                    || List.class.isInstance(map.get(key))
                    || StringUtil.isEmpty(String.valueOf(map.get(key)))
                    || "sign".equals(key)) {
                continue;
            }
            sb.append(key).append("=").append(map.get(key)).append("&");
        }
        sb.setLength(sb.length() - 1);
        return sb.toString();
    }
	
	/**
	 * sha1计算后进行16进制转换
	 * 
	 * @param data
	 *            待计算的数据
	 * @param encoding
	 *            编码
	 * @return 计算结果
	 */
	public static byte[] sha1X16(String data, String encoding) {
		byte[] bytes = sha1(data, encoding);
		StringBuilder sha1StrBuff = new StringBuilder();
		for (int i = 0; i < bytes.length; i++) {
			if (Integer.toHexString(0xFF & bytes[i]).length() == 1) {
				sha1StrBuff.append("0").append(
						Integer.toHexString(0xFF & bytes[i]));
			} else {
				sha1StrBuff.append(Integer.toHexString(0xFF & bytes[i]));
			}
		}
		try {
			return sha1StrBuff.toString().getBytes(encoding);
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}
	
	
	/**
	 * sha1计算
	 * 
	 * @param datas
	 *            待计算的数据
	 * @param encoding
	 *            字符集编码
	 * @return
	 */
	private static byte[] sha1(String datas, String encoding) {
		try {
			return sha1(datas.getBytes(encoding));
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}
	
	/**
	 * sha1计算.
	 * 
	 * @param datas
	 *            待计算的数据
	 * @return 计算结果
	 */
	private static byte[] sha1(byte[] data) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("SHA-1");
			md.reset();
			md.update(data);
			return md.digest();
		} catch (Exception e) {
			return null;
		}
	}
	
	/**
	 * sha256计算后进行16进制转换
	 * 
	 * @param data
	 *            待计算的数据
	 * @param encoding
	 *            编码
	 * @return 计算结果
	 */
	public static byte[] sha256X16(String data, String encoding) {
		byte[] bytes = sha256(data, encoding);
		StringBuilder sha256StrBuff = new StringBuilder();
		for (int i = 0; i < bytes.length; i++) {
			if (Integer.toHexString(0xFF & bytes[i]).length() == 1) {
				sha256StrBuff.append("0").append(
						Integer.toHexString(0xFF & bytes[i]));
			} else {
				sha256StrBuff.append(Integer.toHexString(0xFF & bytes[i]));
			}
		}
		try {
			return sha256StrBuff.toString().getBytes(encoding);
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}
	
	/**
	 * sha256计算
	 * 
	 * @param datas
	 *            待计算的数据
	 * @param encoding
	 *            字符集编码
	 * @return
	 */
	private static byte[] sha256(String datas, String encoding) {
		try {
			return sha256(datas.getBytes(encoding));
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}
	
	/**
	 * sha256计算.
	 * 
	 * @param datas
	 *            待计算的数据
	 * @return 计算结果
	 */
	private static byte[] sha256(byte[] data) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("SHA-256");
			md.reset();
			md.update(data);
			return md.digest();
		} catch (Exception e) {
			
			return null;
		}
	}
	
	
	/**
	 * 页面密码解密，并公钥加密
	 * @param str
	 * @param pwd
	 * @return
	 */
	public static byte[] decrAndEncrByPublicKeyWithPKCS1(String pwd,String key,String path) {
		//解密
		String password = SimpleScriptEncDec.decrypt(pwd,key);
		//加密
		 byte[] enPwd = encryptByPublicKeyWithPKCS1(password.getBytes(),path);
		 
		 return enPwd;
	}
	
	
	/**
	 * 公钥加密
	 * @param src
	 * @param certPath
	 * @return
	 */
	public static byte[] encryptByPublicKeyWithPKCS1(byte[] src, String certPath){
		PublicKey key = null;
		FileInputStream fis = null;
		try{
			CertificateFactory factory = CertificateFactory.getInstance("X.509");
			fis = new FileInputStream(certPath);
			
			X509Certificate cert = (X509Certificate)factory.generateCertificate(fis);
			key = cert.getPublicKey();
		}catch(FileNotFoundException e){
			logger.error("从证书文件读取公钥 - 证书文件不存在：");
			logger.error(e.getMessage(), e);
		}catch(CertificateException e){
			logger.error("从证书文件读取公钥 - 密钥读取异常：");
			logger.error(e.getMessage(), e);
		} finally {
			try {
				if (fis != null)
					fis.close();
			} catch (IOException e) {
				logger.error("关闭证书文件流异常 " + certPath);
			}
		}
		
		byte[] encBytes1 = null;
		try{		
	        //Security.addProvider(new com.allinpay.h5.security.provider.TLSecurityProvider());

			Cipher cipher1 = Cipher.getInstance("RSA/None/PKCS1Padding","BC");
			cipher1.init(Cipher.ENCRYPT_MODE, key);
			encBytes1 = cipher1.doFinal(src);
			
		}catch (NoSuchAlgorithmException e){
			logger.error("公钥加密 - 无效算法：");
		}catch (InvalidKeyException e){
			logger.error("公钥加密 - 无效密钥：");
		}catch (IllegalBlockSizeException e){
			logger.error("公钥加密 - 非法的分块大小：");
		}catch (NoSuchPaddingException e){
			logger.error("公钥加密 - 错误的填充格式：");
		}catch (BadPaddingException e){
			logger.error("公钥加密 - 填充异常：");
		}catch (NoSuchProviderException e){
			logger.error("公钥加密 - 没有此算法提供者：");
		}
		
		return (encBytes1);
		
	}
	
	public static void main(String[] args) {
		try {
			/*FileInputStream privateStream = new FileInputStream("C:\\testAllinpayPrivate.key");
		    FileInputStream publicKeyStream = new FileInputStream("C:\\testAllinpayPublic.key");
		    
			String privateKeyStr = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqt4f8zgcfdu2w7IS" + "\r" +
                    "6rUyiLIQmOnIDj9HBcFy5NcoBoDpiSJ7txmqBtKO0pANrso6Zu5jIBxcgFC1qZPv" + "\r" +
                    "gsJh6QIDAQABAkAsNnnR94z3zCiIjsVyUhyXXmwJBUUs2pbIGHxgVoQW2kwbTnxw" + "\r" +
                    "I2u7IhGUPpW7duzOxA2Kk1Msr79SX88vKjB5AiEA31WlZZGZxQ/V6o5H0NsUifs/" + "\r" +
                    "OSVWk5N9ofBmqq9WdxMCIQDD2/POZnm0+yBRcdb8ozYIQSkbFdeKqyR5pof5Fso2" + "\r" +
                    "kwIgbQnGt+EvfzvtCBixTXI5A+kMBB2LuH+RHgheR8VVZMsCICQ97CRyQ+0gVv+b" + "\r" +
                    "IBwJm3L1k8SmSwcm2g4Eqb6G4A4vAiEAkV5fULSax5TFW3n5k8FA51YhgGlFeWhy" + "\r" +
                    "q/rDpEC+VrU="+ "\r";
			
			String publicKeyKeyStr = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKreH/M4HH3btsOyEuq1MoiyEJjpyA4/" + "\r" +
                    "RwXBcuTXKAaA6Ykie7cZqgbSjtKQDa7KOmbuYyAcXIBQtamT74LCYekCAwEAAQ=="+ "\r";*/
			String publicCertUrl = "/app/conf/mchtCert";
			
			FileInputStream privateStream = new FileInputStream("C:\\private.key");
		    FileInputStream publicKeyStream = new FileInputStream("C:\\public.key");
			
			String signSrc="1111123wwwqq";
			
			//签名
//			PrivateKey privateKey = loadPrivateKeyWithPcks8(privateKeyStr);
			PrivateKey privateKey = loadPrivateKey(privateStream,"PCKS8");
			String signMac=new String(Base64.encode(signByPriKey(privateKey,signSrc.getBytes(),"MD5WithRSA")));
            System.out.println(signMac);
            
            //验签
//          PublicKey publickey=loadPublicKey(publicKeyKeyStr);
            PublicKey publickey =loadPublicKey(publicKeyStream);
			boolean result=verifyByPubKey(publickey,signSrc.getBytes(),Base64.decode(signMac),"MD5WithRSA");
			System.out.println(result);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}
